<template>
  <a-tree
    v-if="treeData.length > 0"
    ref="asyncTreeRef"
    :checkable="checkable"
    :checkStrictly="checkStrictly"
    :load-data="onLoadData"
    :tree-data="treeData"
    :replace-fields="replaceFields"
    :default-expanded-keys="defaultSelectedKeys"
    :default-selected-keys="defaultSelectedKeys"
    v-model:checkedKeys="checkedKeys"
    @select="handlerTreeSelect"
    @check="handlerTreeChecked"
  >
    <template #custom="item">
      <span style="margin-right: 10px">{{ item[replaceFields.title] }} </span>
      <template v-if="showActionIcon">
        <!-- 新增 -->
        <PlusOutlined
          class="tree-custom-icon"
          v-show="item[replaceFields.key] === selectedKey"
          @click.stop="handlerAddIconClick(item)"
        />
        <!-- 修改 -->
        <FormOutlined
          class="tree-custom-icon"
          v-if="item[replaceFields.parentKey] != rootId"
          v-show="selectedKey === item[replaceFields.key]"
          @click.stop="handlerEditIconClick(item)"
        />
        <!-- 删除 -->
        <a-popconfirm
          :title="t('component.tree.deleteTips')"
          @confirm="handlerDeleteIconClick(item)"
        >
          <DeleteOutlined
            class="tree-custom-icon"
            v-if="item[replaceFields.parentKey] != rootId && item.leaf == 0"
            v-show="selectedKey === item[replaceFields.key]"
          />
        </a-popconfirm>
      </template>
    </template>
  </a-tree>
</template>
<script lang="ts">
import { defineComponent, onMounted, reactive, Ref, ref } from "vue";
import {
  PlusOutlined,
  FormOutlined,
  DeleteOutlined,
} from "@ant-design/icons-vue";
import { AsyncTreeProps } from "./interface";
import { isBlankForArray } from "/@/kit/blank-kit";
import { AxiosResponse } from "axios";
import { useI18n } from "vue-i18n";

const customSlot = { title: "custom" };

export default defineComponent({
  name: "QcAsyncTree",
  props: AsyncTreeProps,
  components: {
    PlusOutlined,
    FormOutlined,
    DeleteOutlined,
  },
  emits: [
    "update:checkedKeys",
    "treeSelectChange",
    "treeCheckedChange",
    "addIconClick",
    "editIconClick",
    "DeleteIconClick",
  ],
  setup(props, { emit }) {
    const { t } = useI18n();
    const asyncTreeRef = ref(null);
    const asyncTreePorps = reactive({ ...props });
    //定义一些
    const selectedKey: Ref<string> = ref(null); //select 选中的key
    const defaultSelectedKeys: Ref<Array<string>> = ref([]); //默认选中的key
    const currentNode: Ref<any> = ref(null); //当前选中的node
    const treeData = ref([]); //tree的数据项
    const checkedKeys: Ref<Array<string>> = ref(
      (props.checkedKeys as Array<string>) || []
    ); //checkbox选中的key 如果有默认选中则选择默认

    const _fetchTreeData = (queryParam?: any) =>
      asyncTreePorps.loadData(queryParam);

    //加载顶级数据
    const loadFirstData = () => {
      let queryParam = {};
      queryParam[asyncTreePorps.replaceFields.parentKey] =
        asyncTreePorps.rootId;
      _fetchTreeData(queryParam).then((res: AxiosResponse<any>) => {
        if (isBlankForArray(res.data.data)) return;
        let data = formatDataToTreeData(res.data.data);
        selectedKey.value = data[0][asyncTreePorps.replaceFields.key];
        defaultSelectedKeys.value.push(
          data[0][asyncTreePorps.replaceFields.key]
        );
        treeData.value = data;
        //默认选中的时候,我们也触发一下treenodeselect 这时候获取不到node
        emit(
          "treeSelectChange",
          data[0][asyncTreePorps.replaceFields.key],
          null
        );
      });
    };
    //加载子集数据
    const onLoadData = async (treeNode: any) => {
      if (!currentNode.value) currentNode.value = treeNode; //设置第一级默认node
      let queryParam = {};
      queryParam[asyncTreePorps.replaceFields.parentKey] =
        treeNode.dataRef[asyncTreePorps.replaceFields.key];
      const res = await _fetchTreeData(queryParam);
      treeNode.dataRef.children = formatDataToTreeData(res.data.data);
      treeData.value = [...treeData.value];
    };

    /**
     *格式化数据
     */
    const formatDataToTreeData: any = (data: any) => {
      if (!data || data.length == 0) return [];
      for (let i in data) {
        data[i].isLeaf = !(data[i].leaf && data[i].leaf > 0);
        //查看是否有叶子节点
        data[i].slots = customSlot;
        //处理禁止选中的数据
        if (
          props.disabledKeys &&
          props.disabledKeys.indexOf(
            data[i][asyncTreePorps.replaceFields.key]
          ) != -1
        ) {
          data[i].disableCheckbox = true;
        }
      }
      return data;
    };

    /**
     * 刷新当前节点
     */
    const refreshCurrentNode = () => {
      currentNode.value.dataRef.isLeaf = false;
      currentNode.value.dataRef.children = [];
      onLoadData(currentNode.value); //刷新当前node
    };
    /**
     *刷新当前节点父节点
     */
    const refreshParentNode = () => {
      let parentNode = currentNode.value.vcTreeNode;
      parentNode.dataRef.children = [];
      onLoadData(parentNode); //刷新父节点node
    };

    /////////////////////////监听事件/////////
    const handlerTreeSelect = (
      selectedKeys: Array<string>,
      { selected, node }
    ) => {
      if (selected === false) return;
      selectedKey.value = selectedKeys[0].trim();
      currentNode.value = node;
      //异步树我们不做多选 只有单选 所以只选择第一个
      emit("treeSelectChange", selectedKeys[0], node);
    };

    const handlerTreeChecked = (treeCheckedKeys: Array<string>) => {
      checkedKeys.value = treeCheckedKeys;
      emit("update:checkedKeys", checkedKeys.value);
      emit("treeCheckedChange", treeCheckedKeys);
    };

    ////////////////////////自定义方法/////////////////////
    const handlerAddIconClick = (item: any) => emit("addIconClick", item);
    const handlerEditIconClick = (item: any) => emit("editIconClick", item);
    const handlerDeleteIconClick = (item: any) => emit("DeleteIconClick", item);

    onMounted(() => loadFirstData());
    return {
      asyncTreeRef,
      t,
      ...asyncTreePorps,
      checkedKeys,
      selectedKey,
      defaultSelectedKeys,
      treeData,
      onLoadData,
      refreshCurrentNode,
      refreshParentNode,
      handlerTreeSelect,
      handlerTreeChecked,
      handlerAddIconClick,
      handlerEditIconClick,
      handlerDeleteIconClick,
    };
  },
});
</script>

<style lang="less" scoped>
.tree-custom-icon {
  padding: 0 4px;
}
</style>